package cn.iocoder.boot.springai001.example;

import cn.iocoder.boot.springai001.controller.dto.ChatRequest;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

/**
 * 思维链（Chain of Thought）功能使用示例
 * 
 * 本示例展示如何通过 HTTP 客户端调用支持 CoT 的 AI 对话接口
 * 
 * @author iocoder
 */
public class ChainOfThoughtExample {

    private static final String BASE_URL = "http://localhost:8080";
    private static final WebClient webClient = WebClient.create(BASE_URL);

    /**
     * 示例1：使用 Zero-shot CoT 解决数学问题
     */
    public static void example1_ZeroShotCoT_Math() {
        System.out.println("=== 示例1：Zero-shot CoT 数学问题 ===\n");

        String query = "当我3岁时，我的伴侣是我年龄的3倍。现在我20岁了，我的伴侣多大？";

        Flux<String> response = webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/api/v1/chat")
                        .queryParam("query", query)
                        .queryParam("enableCoT", true)
                        .queryParam("cotMode", "ZERO_SHOT")
                        .queryParam("model", "gpt-4o")
                        .queryParam("temperature", 0.5)
                        .build())
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        response.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n\n完成！")
        );
    }

    /**
     * 示例2：使用 Few-shot CoT 解决逻辑推理问题（默认示例）
     */
    public static void example2_FewShotCoT_DefaultExample() {
        System.out.println("=== 示例2：Few-shot CoT 逻辑推理（默认示例） ===\n");

        String query = "一个商店的苹果价格是每斤5元，今天打8折，我买了3斤，需要付多少钱？";

        Flux<String> response = webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/api/v1/chat")
                        .queryParam("query", query)
                        .queryParam("enableCoT", true)
                        .queryParam("cotMode", "FEW_SHOT")
                        .queryParam("model", "gpt-4o")
                        .queryParam("temperature", 0.5)
                        .build())
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        response.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n\n完成！")
        );
    }

    /**
     * 示例3：使用 POST 请求和自定义 Few-shot 示例
     */
    public static void example3_FewShotCoT_CustomExample() {
        System.out.println("=== 示例3：Few-shot CoT 自定义示例 ===\n");

        // 构建请求对象
        ChatRequest request = new ChatRequest();
        request.setQuery("一个水池有两个进水管，A管每小时进水10立方米，B管每小时进水15立方米。如果同时打开两个管，3小时能进多少水？");
        request.setPrompt("你是一个擅长数学计算的AI助手");
        request.setModel("gpt-4o");
        request.setTemperature(0.5);
        request.setEnableCoT(true);
        request.setCotMode(ChatRequest.CoTMode.FEW_SHOT);
        
        // 自定义示例
        String customExample = 
            "Q: 一个池子有两个排水管，A管每小时排水5立方米，B管每小时排水8立方米。" +
            "如果同时打开两个管，2小时能排多少水？让我们逐步思考。\n" +
            "A: A管2小时排水 5 × 2 = 10立方米，B管2小时排水 8 × 2 = 16立方米。" +
            "同时打开时，总共排水 10 + 16 = 26立方米。答案是26立方米。";
        request.setCotExample(customExample);

        Flux<String> response = webClient.post()
                .uri("/api/v1/chat/session/1000000000000001")
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(request)
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        response.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n\n完成！")
        );
    }

    /**
     * 示例4：对比不使用 CoT 和使用 CoT 的效果
     */
    public static void example4_CompareWithAndWithoutCoT() {
        System.out.println("=== 示例4：对比效果 ===\n");

        String query = "一个数字加上它的一半等于15，这个数字是多少？";

        // 不使用 CoT
        System.out.println("【不使用 CoT】");
        Flux<String> withoutCoT = webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/api/v1/chat")
                        .queryParam("query", query)
                        .queryParam("enableCoT", false)  // 关闭 CoT
                        .queryParam("model", "gpt-4o")
                        .queryParam("temperature", 0.5)
                        .build())
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        withoutCoT.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n")
        );

        // 等待一段时间后使用 CoT
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("\n【使用 Zero-shot CoT】");
        Flux<String> withCoT = webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/api/v1/chat")
                        .queryParam("query", query)
                        .queryParam("enableCoT", true)  // 启用 CoT
                        .queryParam("cotMode", "ZERO_SHOT")
                        .queryParam("model", "gpt-4o")
                        .queryParam("temperature", 0.5)
                        .build())
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        withCoT.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n\n完成！")
        );
    }

    /**
     * 示例5：复杂的多步骤推理问题
     */
    public static void example5_ComplexReasoning() {
        System.out.println("=== 示例5：复杂多步骤推理 ===\n");

        String query = 
            "一个班级有40个学生，其中60%是女生。" +
            "在女生中，25%戴眼镜。" +
            "在男生中，50%戴眼镜。" +
            "这个班级一共有多少学生戴眼镜？";

        ChatRequest request = new ChatRequest();
        request.setQuery(query);
        request.setPrompt("你是一个擅长数学推理的AI助手，请详细展示每一步的计算过程");
        request.setModel("gpt-4o");
        request.setTemperature(0.3);  // 较低温度，获得更稳定的推理
        request.setEnableCoT(true);
        request.setCotMode(ChatRequest.CoTMode.ZERO_SHOT);

        Flux<String> response = webClient.post()
                .uri("/api/v1/chat/session/1000000000000002")
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(request)
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        response.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n\n完成！")
        );
    }

    /**
     * 示例6：在会话中持续使用 CoT
     */
    public static void example6_SessionWithCoT() {
        System.out.println("=== 示例6：会话中持续使用 CoT ===\n");

        String sessionId = "1000000000000003";

        // 第一个问题
        System.out.println("【问题1】");
        ChatRequest request1 = new ChatRequest();
        request1.setQuery("小明有10个苹果，吃了2个，又买了5个，现在有多少个？");
        request1.setEnableCoT(true);
        request1.setCotMode(ChatRequest.CoTMode.ZERO_SHOT);

        sendChatRequest(sessionId, request1);

        // 等待响应
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 第二个问题（基于前面的上下文）
        System.out.println("\n【问题2】");
        ChatRequest request2 = new ChatRequest();
        request2.setQuery("如果小明再给小红3个苹果，他还剩多少个？");
        request2.setEnableCoT(true);
        request2.setCotMode(ChatRequest.CoTMode.ZERO_SHOT);

        sendChatRequest(sessionId, request2);
    }

    /**
     * 辅助方法：发送聊天请求
     */
    private static void sendChatRequest(String sessionId, ChatRequest request) {
        Flux<String> response = webClient.post()
                .uri("/api/v1/chat/session/" + sessionId)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(request)
                .accept(MediaType.TEXT_EVENT_STREAM)
                .retrieve()
                .bodyToFlux(String.class);

        response.subscribe(
                chunk -> System.out.print(chunk),
                error -> System.err.println("错误: " + error.getMessage()),
                () -> System.out.println("\n")
        );
    }

    /**
     * 主方法 - 运行所有示例
     */
    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("思维链（Chain of Thought）功能示例");
        System.out.println("========================================\n");

        // 运行示例（取消注释以运行）
        
        // 示例1：Zero-shot CoT 数学问题
        // example1_ZeroShotCoT_Math();

        // 示例2：Few-shot CoT 默认示例
        // example2_FewShotCoT_DefaultExample();

        // 示例3：Few-shot CoT 自定义示例
        // example3_FewShotCoT_CustomExample();

        // 示例4：对比效果
        // example4_CompareWithAndWithoutCoT();

        // 示例5：复杂推理
        // example5_ComplexReasoning();

        // 示例6：会话中使用 CoT
        // example6_SessionWithCoT();

        System.out.println("\n提示：请取消注释 main 方法中的示例代码来运行具体示例");
    }

    /**
     * 推荐的使用场景和配置
     */
    public static class BestPractices {
        
        /**
         * 数学问题推荐配置
         */
        public static ChatRequest mathProblemConfig(String query) {
            ChatRequest request = new ChatRequest();
            request.setQuery(query);
            request.setPrompt("你是一个擅长数学计算的AI助手，请详细展示每一步的计算");
            request.setModel("gpt-4o");
            request.setTemperature(0.3);  // 低温度，准确性优先
            request.setEnableCoT(true);
            request.setCotMode(ChatRequest.CoTMode.ZERO_SHOT);
            return request;
        }

        /**
         * 逻辑推理问题推荐配置
         */
        public static ChatRequest logicReasoningConfig(String query) {
            ChatRequest request = new ChatRequest();
            request.setQuery(query);
            request.setPrompt("你是一个擅长逻辑推理的AI助手");
            request.setModel("gpt-4o");
            request.setTemperature(0.5);
            request.setEnableCoT(true);
            request.setCotMode(ChatRequest.CoTMode.ZERO_SHOT);
            return request;
        }

        /**
         * 需要特定推理模式的问题（使用 Few-shot）
         */
        public static ChatRequest specificReasoningConfig(String query, String example) {
            ChatRequest request = new ChatRequest();
            request.setQuery(query);
            request.setPrompt("你是一个乐于助人的AI助手");
            request.setModel("gpt-4o");
            request.setTemperature(0.5);
            request.setEnableCoT(true);
            request.setCotMode(ChatRequest.CoTMode.FEW_SHOT);
            request.setCotExample(example);
            return request;
        }
    }
}

